package org.streets.eis.component.organcombobox;

import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.string.Strings;
import org.streets.commons.util.JDBCUtils;
import org.streets.database.Limits;
import org.streets.database.SQLConnection;
import org.streets.database.SQLNestedException;
import org.streets.eis.EisWebSession;
import org.streets.eis.component.WebResources;
import org.streets.eis.component.combobox.TreeComboBox;
import org.streets.eis.component.model.DataModel;
import org.streets.eis.component.model.ListItem;
import org.streets.eis.entity.User;
import org.streets.eis.ext.rbac.services.RBACAuthorizer;
import org.streets.eis.types.UnitType;
import org.streets.wicket.HiveWebApplication;

public class OrganComboBox extends TreeComboBox {

	private static final long serialVersionUID = 1L;

	private String[] rootOrganIds;

	@Inject
	private SQLConnection connection;
	@Inject
	private RBACAuthorizer authorizer;
	
	public OrganComboBox(String id){
		this(id,false);
	}
	public OrganComboBox(String id,boolean canInput){
		this(id,canInput,new String[]{});
	}
	
	public OrganComboBox(String id, String... rootOrganId){
		this(id,false,rootOrganId);		
	}
		
	public OrganComboBox(String id, boolean canInput,String... rootOrganId){
		super(id,null,canInput);
		setOnlySelectLeaf(false);		
		setRootOrganIds(rootOrganId);		
	}	
	
	
	public OrganComboBox(String id, IModel<ListItem> model){
		this(id,model,false);
	}
	
	public OrganComboBox(String id, IModel<ListItem> model,String... rootOrganId){
		this(id,model,false,rootOrganId);
	}
	
	public OrganComboBox(String id, IModel<ListItem> model,boolean canInput){
		this(id,model,false,new String[]{});
	}
	
	public OrganComboBox(String id, IModel<ListItem> model,boolean canInput,String... rootOrganId){
		super(id,model,null,false);
		setOnlySelectLeaf(false);
		setRootOrganIds(rootOrganId);
	}
	
	public String[] getRootOrganIds() {
		return rootOrganIds;
	}

	public void setRootOrganIds(String... rootOrganId) {
		this.rootOrganIds = rootOrganId;
		setDataModel(generateDataModel());
	}
	
	protected String generateSqlOR(String fieldName,String[] array){
		StringBuffer sb = new StringBuffer("(1=0 ");
		for (String key : array){
			sb.append(" OR ").append(fieldName).append("='").append(key).append("'");
		}
		sb.append(")");
		return sb.toString();
	}
	
	public DataModel<ListItem> generateDataModel(){
		
		User user = EisWebSession.get().getUser();
		String userOrganSql = authorizer.generateUserOrganPermitSql(user);
		
		boolean flag = rootOrganIds!=null && rootOrganIds.length>0;
		String organSql  = "";
		
		if (flag){ 
			organSql = String.format("SELECT ID,NAME,ATTR,(CASE WHEN EXISTS(SELECT ID FROM EIS_ORGAN WHERE PARENT_ID=a.ID AND ID IN (%s)) THEN 1 ELSE 0 END) FROM EIS_ORGAN a WHERE %s AND ID IN (%s)  ORDER BY SHOW_INDEX",
					userOrganSql,generateSqlOR("ID",rootOrganIds),userOrganSql);
			flag = connection.count(organSql) > 0;
		}
		if (!flag) {
			organSql = String.format("SELECT ID,NAME,ATTR,(CASE WHEN EXISTS(SELECT ID FROM EIS_ORGAN WHERE PARENT_ID=a.ID AND ID IN (%s)) THEN 1 ELSE 0 END) FROM EIS_ORGAN a WHERE ID IN (%s) AND nvl(PARENT_ID,'#') NOT IN (%s)  ORDER BY SHOW_INDEX",
				userOrganSql,userOrganSql,userOrganSql);	
		}
		
		ResultSet rs = connection.query(organSql, Limits.none());
		DataModel<ListItem> model = new DataModel<ListItem>();
		try{
			while (rs.next()){
				DataModel<ListItem> tmp = new DataModel<ListItem>(new ListItem(rs.getString(1),rs.getString(2),getIcon(rs.getString(3))));
				if (rs.getInt(4)==1) tmp.addChild(TreeComboBox.DUMMY);
				model.addChild(tmp);
			}
		} catch (Exception ex) {
			throw new SQLNestedException(organSql, ex);
		} finally {
			JDBCUtils.close(rs);
		}		

		return model;
	}
	
	@Override
	protected Iterator<ListItem> getMatchedItems(String key) {
		
		User user = EisWebSession.get().getUser();
		
		String userOrganSql = authorizer.generateUserOrganPermitSql(user);
		
		String sql = String.format("SELECT ID,NAME,ATTR FROM EIS_ORGAN a WHERE %s AND ID IN (%s) ORDER BY SHOW_INDEX",
				generateLikeSql("NAME",key),userOrganSql);

		ResultSet rs = connection.query(sql, Limits.of(0, 10));
		List<ListItem> matcheds = new ArrayList<ListItem>();
		try{
			while (rs.next()){
				matcheds.add(new ListItem(rs.getString(1),rs.getString(2),getIcon(rs.getString(3))));
			}
		} catch (Exception ex) {
			throw new SQLNestedException(sql, ex);
		} finally {
			JDBCUtils.close(rs);
		}
		return matcheds.iterator();
	}

	@Override
	protected List<DataModel<ListItem>> generateChildrenDataModel(String parentId) {
		User user = EisWebSession.get().getUser();
		
		RBACAuthorizer authorizer = HiveWebApplication.get().getRegistry().service(RBACAuthorizer.class);
		String userOrganSql = authorizer.generateUserOrganPermitSql(user);
		
		String sql = String.format("SELECT ID,NAME,ATTR,(CASE WHEN EXISTS(SELECT ID FROM EIS_ORGAN WHERE PARENT_ID=a.ID AND ID IN (%s)) THEN 1 ELSE 0 END) FROM EIS_ORGAN a WHERE PARENT_ID='%s' AND ID IN (%s) ORDER BY SHOW_INDEX",
				userOrganSql,parentId,userOrganSql);
		ResultSet rs = connection.query(sql, Limits.none());
		DataModel<ListItem> model = new DataModel<ListItem>();
		try{
			while (rs.next()){
				DataModel<ListItem> tmp = new DataModel<ListItem>(new ListItem(rs.getString(1),rs.getString(2),getIcon(rs.getString(3))));
				if (rs.getInt(4)==1) tmp.addChild(TreeComboBox.DUMMY);
				model.addChild(tmp);
			}
		} catch (Exception ex) {
			throw new SQLNestedException(sql, ex);
		} finally {
			JDBCUtils.close(rs);
		}
		return model.getChildren();
	}
	
	private String getIconUrl(ResourceReference reference){
		return reference.getScope().getName() + "/" + reference.getName();
	}
	
	protected String getIcon(String attr){
		if (Strings.isEmpty(attr)){
			return getIconUrl(WebResources.Streets.Organ.DEPT_ICON);
		}
		
		if (attr.equals(String.valueOf(UnitType.GROUP.value()))){
			return getIconUrl(WebResources.Streets.Organ.ENT_ICON);
		} else if (attr.equals(String.valueOf(UnitType.COMPANY.value()))){
			return getIconUrl(WebResources.Streets.Organ.COMP_ICON);
		} else{
			return getIconUrl(WebResources.Streets.Organ.DEPT_ICON);
		}
	}
	
	@Override
	protected void onItemChanged(ListItem newValue){
		onItemChanged(this,newValue);
	}

	@Override
	protected void onAjaxItemChanged(ListItem newValue,AjaxRequestTarget target){
		onAjaxItemChanged(this,newValue,target);
	}		
	
	protected void onItemChanged(OrganComboBox organComboBox,ListItem newValue){		
	}
	
	protected void onAjaxItemChanged(OrganComboBox organComboBox,ListItem newValue,AjaxRequestTarget target){	
	}	

}
